﻿/*!
 * 树节点对象.
 * ecp.qzz.expression.js
 * 创建：QZZ
 * 日期：2014-03-01
 */
define(["qzz.object"], function() {
	var qzz = window.qzz;
	
	/**
	 * 表达式类
	 * @class Expression
	 * @author qinzhenzhou@ygsoft.com
	 * @date 2014.3.1
	 */
	qzz.expression = qzz.Class(/**@lends Expression */{
		/**
		 * 初始化函数.
		 * @param {String} expStr 表达式串
		 * @param {String} caption
		 */
		init:function(expStr, caption) {		
			this.className = "Expression";
			//公式类型
			this.expType = {
			    ftField:"FIELD",
			    ftCell:"CELL",
			    ftFunction:"FUNCTION",
			    ftNone:"None"
			}
			//公式表达式字符串.
			this.exp = expStr;
			this.caption = caption;
			//公式列表
			this._expStack = [];
			this._top = 0;
			//元素对象列表
			this._expObject = [];
			//数据源
			this.dataSource = {
			     "dataSet":null
			}
			//公式提示信息
			this.msg = "";
			//公式等级.
			this.state = 0;
			//公式拆分符.
			this.fieldSplit = "$";
			this.valueSplit = "_";
			this.keySplit = "~~";
			this.nodeBegin = "#{";
			this.nodeEnd = "}";
			this.pathSplit = ".";
	    },
	    /**
	     * 判断当前单元格是否在列表中.
	     * <p>
	     *  如果公示列表中，没有对应的单元格，则返回 -1
	     * </p>
	     * @param {String} fieldName 列字段名称
	     * @param {String} keyFieldName 索引列字段
	     * @param {String} value 索引列值
	     * @returns {Number} 返回单元格在公式中的序号
	     */
	    indexOf:function(fieldName, keyFieldName, value) {
	    	var len = this._expObject.length;
	    	var re = -1;
	    	for(var i = 0; i < len; i++) {
	    		var co = this._expObject[i];
	    		//判断是否一样.
	    		if(co.fieldName === fieldName 
	    				&& (co.type === this.expType.ftField 
	    						|| co.type === this.expType.ftCell 
	    						    && co.keyFieldName === keyFieldName
	    						        && co.keyValue === value)) {
	    			re = i;
	    			break;
	    		}
	    		co = null;
	    	}
	    	co = null;
	    	return re;
	    },
	    /**
	     * 设置公式.
	     * @param {String} fieldName 列字段名称
	     * @param {String} keyFieldName 索引列字段
	     * @param {String} value 索引列值
	     * @param {String} expStr 表达式串
	     */
	    setExpression:function(fieldName, keyFieldName, value, expStr) {
	    	if(value == null && expStr == null && keyFieldName != null) {
	    		expStr = keyFieldName;
	    		keyFieldName = undefined;
	    	}	     
	    	this.setFieldName(fieldName);
	    	if(keyFieldName != null && value != null) {
	    	    this.setKeyFieldName(keyFieldName, value);
	    	}	    	
	    	if(typeof expStr == "string") {
	    	    this.exp = expStr;
	    	    this.caption = expStr;
	    	} else {
	    		this.exp = expStr.exp;
	    		this.caption = expStr.caption;
	    	}
	    	if(this.dataSource.dataSet != null) {
	    	    this.decode();
	    	}	    	
	    },
	    /**
	     * 设置勾稽公式.
	     * @param {String} keyFieldName 索引列字段
	     * @param {String} expStr 表达式串
	     */
	    setGJExpression:function(keyFieldName, expStr) {
	    	if(keyFieldName != null) {
	    	    this.setKeyFieldName(keyFieldName, "");
	    	}
	    	if(typeof expStr == "object") {
	    		this.exp = expStr.exp;
	    		this.caption = expStr.caption;
	    		this.sumitState = expStr.sumitState;
	    		this.messageState = expStr.messageState;
	    		this.message = expStr.message;
	    		if(this.dataSource.dataSet != null) {
		    	    this.decode();
		    	}
	    		var len = this._expObject.length;
	    		for(var i = 0; i < len; i++) {
	    			var exp = this._expObject[i];
	    			if(exp.node == null) {
	    			    exp.node = this.getDataSet().getKeyNode(exp.keyFieldName, exp.keyValue);
	    			}
	    			var op = this.getDataSet().getCellOption(exp.fieldName, exp.node);
	    			op.GJTitle = this.caption;
	    			op.isCac = true;
	    			op = null;
	    			exp = null;
	    		}
	    	}	    	
	    },
	    /**
	     * 设置数据源.
	     * @param {Object} dataSet 数据集
	     */
	    setDataSet:function(dataSet) {
	    	this.dataSource.dataSet = dataSet;
	    },

	    /**
	     * 获取数据集.
	     * @returns {Object}
	     */
	    getDataSet:function() {
	        return this.dataSource.dataSet;
	    },

	    /**
	     * 设置字段.
	     * @param {String} fieldName 字段名称
	     */
	    setFieldName:function(fieldName) {
	        this.fieldName = fieldName;
	    },	    
	    /**
	     * 设置行节点对象.
	     * @param {String} fieldName 字段名称
	     * @param {String} value 索引列值
	     */
	    setKeyFieldName:function(fieldName, value) {
	    	 if(typeof fieldName === "string") {	     
		    	 this.keyFieldName = fieldName;
		    	 this.keyValue = value;
	    	 } else if(this.isArray(fieldName) && value instanceof Array) {
	    		 this.keyFieldName = fieldName.join(this.fieldSplit);
	    		 this.keyValue = value.join(this.fieldSplit);	    		 
	    	 }
	    	 
	    },
		/**
		 * 去除左右边的空格符.
		 * str  字符串
		 */
		trim:function(str) {
			if(str != null && str !== "" && typeof str == "string") {
				str = str.replace(/(^\s*)|(\s*$)/g,"");
			}
			return str;
		},
	    /**
	     * 分解运算公式.
	     */
	    decode:function() {
	    	 //(/([^><=!])([=]+)/g, "$1==") 把等于号替换
	    	 //(/<>/g, "!=") 把不等于号替换    
	    	 //(/isNull/g, "==null") 把为空替换为 == null   
	    	 //(/isNotNull/g, "!=null") 把不为空替换成 != null
	    	 var replaceJson = {"<>":"!=", "isNull":"==null", "isNotNull":"!=null"};
	    	 var tmpstr = this.exp.replace(/([^><=!])([=]+)|<>|isNull|isNotNull/g, function(key, $1, $2) {
	    	       var key = replaceJson[key];
	    	       if(key == null) {
	    	           key = $1 + "==";
	    	       }
	    	       return key;
	    	 });
	    	 replaceJson = null;
	    	 var k = 0;
	    	 this._top = 0;
	    	 var i = tmpstr.indexOf(this.nodeBegin);
	    	 while(i >= 0) {
	    	     var substr = tmpstr.substring(0, i);
	    	     if(substr.length > 0) {
	    	         this._expStack[this._top++] = substr;
	    	     }
	    	     tmpstr = tmpstr.substring(i + 2);
	    	     var j = tmpstr.indexOf(this.nodeEnd);
	    	     if(j >= 0) {
	    	    	 //获取节点字符串	    	     
	    	         var fstr = tmpstr.substring(0, j);
	    	         tmpstr = tmpstr.substring(j+1);
	    	         //fstr = vo$flgid@billid1_1  fmAry = [vo$flgid, billid1_1]
	    	         fmAry = fstr.split(this.keySplit);
	    	         //处理fieldName fnAry = [vo,flgid]
	    	         fnAry = fmAry[0].split(this.fieldSplit);
	    	         //删除掉第一个 fnAry = [flgid]
	    	         if(fnAry.length > 1 && fnAry[0] === this.getDataSet().getName()) {
	    	             fnAry.splice(0, 1);
	    	         }
	    	         var element = {};
	    	         element.fieldName = fnAry.join(this.pathSplit);
    	        	 element.index = this._top;
	    	         if(fmAry.length < 2) {	    	        	 
	    	        	 element.type = this.expType.ftField;
	    	        	 //当前列变更的时候，公式需要重新运算 
	    	             var cm = this.getDataSet().getFieldOption(element.fieldName);
	    	             if(this.fieldName != null) {
	    	                 cm.cacPFields[this.fieldName] = this.getDataSet().getFieldOption(this.fieldName);
	    	             }
	    	             cm = null;
	    	         } else {
	    	        	 element.type = this.expType.ftCell;
	    	        	 //行定位  BILLID1_1
	    	        	 frAry = fmAry[1].split(this.valueSplit);
	    	        	 element.keyFieldName = frAry[0];
	    	        	 element.keyValue = frAry[1];
	    	        	 element.node = this.getDataSet().getKeyNode(frAry[0], frAry[1]);
	    	        	 if(element.node != null) {
		    	        	 //当前单元格变更的时候，公式需要重新运算 		    	        	 
		   	        		 var op = this.getDataSet().getCellOption(element.fieldName, element.node);	    	        	 
		   	        		 var nodeKey = this.fieldName + this.keySplit + this.keyFieldName + this.valueSplit + this.keyValue;
		   	        		 if(op.cacPCells == null) {
		   	        			op.cacPCells = {};
		   	        		 }
		   	        		 //获取公式所在的行节点 
			    	         if(this.keyNode == null) {
			    	        	 this.keyNode = this.getDataSet().getKeyNode(this.keyFieldName, this.keyValue); 
			    	         }
			    	         if(this.keyNode != null) {
			    	        	 op.cacPCells[nodeKey] = {
			   	        	                 "node":this.keyNode,
			   	        	                 "fieldName":this.fieldName,
			   	        	                 "keyFieldName":this.keyFieldName,
			   	        	                 "keyValue":this.keyValue
			   	        	              };
			   	        	     op.isCac = true;
		   	        	     }
		   	        	     op = null;
	   	        	     }
	   	        	 }	 
	    	         this._expObject[k++] = element;
	    	         this._expStack[this._top++] = 0;
	    	     }
 	             i = tmpstr.indexOf(this.nodeBegin);
 	        }
 	        if(tmpstr.length > 0) {
 	            this._expStack[this._top++] = tmpstr;
 	        }
 	    },
 	    /**
 	     * 获取公式运算结果.
 	     * @param {TreeNode} node 行节点
 	     * @param {Boolean} notEval 运算
 	     * @return {String} 返回表达式，或运算结果.
 	     */
 	    getValue:function(node, notEval) {
 	    	var len = this._expObject.length;
 	    	for(var i = 0; i < len; i++) {
 	    		var el = this._expObject[i];
 	    		var val = 0;
 	    		if(el.type === this.expType.ftField) {
 	    			val = this.getDataSet().getValue(el.fieldName, node);
 	    		} else { 	    
 	    			if(el.node == null) {
	    	        	el.node = this.getDataSet().getKeyNode(el.keyFieldName, el.keyValue); 
	    	        	if(el.node != null) {
	    	        		 //当前单元格变更的时候，公式需要重新运算 		    	        	 
		   	        		 var op = this.getDataSet().getCellOption(el.fieldName, el.node);	    	        	 
		   	        		 var nodeKey = this.fieldName + this.keySplit + this.keyFieldName + this.valueSplit + this.keyValue;
		   	        		 if(op.cacPCells == null) {
		   	        			op.cacPCells = {};
		   	        		 }
		   	        		 //获取公式所在的行节点 
			    	         if(this.keyNode == null) {
			    	        	 this.keyNode = this.getDataSet().getKeyNode(this.keyFieldName, this.keyValue); 
			    	         }
			    	         if(this.keyNode != null) {
			    	        	 op.cacPCells[nodeKey] = {
			   	        	                 "node":this.keyNode,
			   	        	                 "fieldName":this.fieldName,
			   	        	                 "keyFieldName":this.keyFieldName,
			   	        	                 "keyValue":this.keyValue
			   	        	              };
			   	        	     op.isCac = true;
		   	        	     }
		   	        	     op = null;
	    	        	}
 	    			}
 	    			if(el.node != null) {
 	    			    val = this.getDataSet().getValue(el.fieldName, el.node);
 	    			} 	    			    
 	    		}
 	    		//有一个为空时，直接返回空
// 	    		if(notEval !== true && val === "") {
// 	    			return "";
// 	    		}
 	    		if(val == null || val === "") {
 	    			val = 0;
 	    		}
 	    		this._expStack[el.index] = val;
 	    		el = null;
 	    	}
 	    	var rs = this._expStack.join("");
 	    	if(notEval) {
 	    		return rs;
 	    	} else {
	 	    	if(this.trim(rs) !== "") {
	 	    		return eval("("+rs+")");
	 	    	}
 	    	} 	    	
 	    }
	 });
	 return qzz.expression;
});
	